import { glob } from "glob";
import { basename, dirname, extname, format, join, relative } from "path";
import fs from "fs";
import  globToRegex from 'glob-to-regexp'

import {transformSync} from '@babel/core'
// function globSync(pattern, root) {
//    root = root || process.cwd();
//   const regex = globToRegex(pattern);
  
//   return files.filter(file => regex.test(file));
// }


const getModels = ({ pattern, base }) => {
  return glob.sync(pattern || "**/*.{ts,js}", {
    cwd: base,
    absolute: true,
  });
};

export function winPath(path: string) {
  const isExtendedLengthPath = /^\\\\\?\\/.test(path);
  if (isExtendedLengthPath) {
    return path;
  }
  return path.replace(/\\/g, "/");
}

export function getNamespace(absFilePath: string, absSrcPath: string) {
  const relPath = winPath(relative(winPath(absSrcPath), winPath(absFilePath)));
  const parts = relPath.split("/");
  const dirs = parts.slice(0, -1);
  const file = parts[parts.length - 1];
  // src/pages/foo/models/bar > foo/bar
  const validDirs = dirs.filter(
    (dir) => !["src", "pages", "models"].includes(dir)
  );
  let normalizedFile = file;
  normalizedFile = basename(file, extname(file));
  // foo.model > foo
  if (normalizedFile.endsWith(".model")) {
    normalizedFile = normalizedFile.split(".").slice(0, -1).join(".");
  }
  return [...validDirs, normalizedFile].join(".");
}

const getList = () => {
  const imports: string[] = [];
  const modelProps: string[] = [];
  const models = [];

  [
    ...getModels({
      base: join("./src", "models"),
      pattern: "**/*.{ts,tsx,js,jsx}",
    }),

    ...getModels({
      base: join("./src/pages"),
      pattern: "**/models/**/*.{ts,tsx,js,jsx}",
    }),
    ...getModels({
      base: join("./src"),
      pattern: "**/model.{ts,tsx,js,jsx}",
    }),
  ].forEach((item, index) => {
    const modelId = `model_${index}`;
    imports.push(`import ${modelId}  from '${winPath(item)}'`);
    modelProps.push(
      `${modelId}: { namespace: '${getNamespace(
        item,
        "./src"
      )}', model: ${modelId} },`
    );
    models.push({
      namespace:getNamespace(
        item,
        "./src"
      ),
      model:modelId
    })
  });
  const modelFile = `
  ${imports.join("\n")}
  
  export const models = {
  ${modelProps.join("\n")}
  } as const`;
  console.log(models)
  fs.writeFileSync(join("./src", "/.qps/plugin-model/model.ts"), modelFile);
};

const  topologicalSort = (models:any) => {
  // build depts graph
  const graph: Array<any | undefined> = [];
  const namespaceToNode: Record<string, any> = {};
  models.forEach((model, index) => {
    const node = {
      namespace: model.namespace,
      deps: model.deps,
      index,
      in: 0,
      childs: [],
    };
    if (namespaceToNode[model.namespace]) {
      throw new Error(`Duplicate namespace in models: ${model.namespace}`);
    }
    namespaceToNode[model.namespace] = node;
    graph.push(node);
  });

  // build edges.
  (graph).forEach((node) => {
    node.deps.forEach((dep) => {
      const depNode = namespaceToNode[dep];
      if (!depNode) {
        throw new Error(`Model namespace not found: ${dep}`);
      }
      depNode.childs.push(node);
      node.in++;
    });
  });

  const queue: string[] = [];
  while (true) {
    // find first 0 in node;
    const zeronode = graph.find((n) => {
      return n && n.in === 0;
    });
    if (!zeronode) {
      break;
    }

    queue.push(zeronode.namespace);
    zeronode.childs.forEach((child) => {
      child.in--;
    });
    zeronode.childs = [];
    delete graph[zeronode.index];
  }

  const leftNodes = graph.filter(Boolean);
  if (leftNodes.length > 0) {
    throw new Error(
      `Circle dependency detected in models: ${leftNodes}` );
  }

  return queue;
};

export default function myPlugin() {
  return {
    name: "qps-plugin-model",
    configureServer() {
      // getList();
      const content = fs.writeFileSync(join("./src", "/.qps/plugin-model/model.ts"), 'utf-8');

      const result = transformSync(content, {
        sourcemap: false,
        minify: false,
      });
      console.log(result)
    },
    // async resolveId(source, importer, options){
    //      console.log("resolveId==>",source);
    //      return null;
    // },
   
    // load(id) {
    //  // console.log("load===>",id)

    //     // const regex = globToRegex(`${join(process.cwd(),"./src", "models")}/**/*.{ts,tsx,js,jsx}`);
    //     //  console.log(regex,id)
    //     //  if(regex.test(id))  {
    //     //   console.log("load===>",id)
    //     //  }
    // },
    // transform(code, id){
    //  // console.log(id)
    // },
    
  };
}
